package cn.tqfeiyang.springplus.generator.engine;

import cn.tqfeiyang.springplus.generator.config.GeneratorConfig;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Properties;

/**
 * Velocity 模板引擎实现文件输出
 */
public class VelocityTemplateEngine extends TemplateEngine {

    private static final Logger LOGGER = LoggerFactory.getLogger(VelocityTemplateEngine.class);

    String VM_LOAD_PATH_KEY = "file.resource.loader.class";

    String VM_LOAD_PATH_VALUE = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";

    String UTF8 = StandardCharsets.UTF_8.name();

    private VelocityEngine velocityEngine;

    {
        try {
            Class.forName("org.apache.velocity.util.DuckType");
        } catch (ClassNotFoundException e) {
            // velocity1.x的生成格式错乱 https://github.com/baomidou/generator/issues/5
            LOGGER.warn("Velocity 1.x is outdated, please upgrade to 2.x or later.");
        }
    }

    public VelocityTemplateEngine(GeneratorConfig generatorConfig) {
        super(generatorConfig);
        Properties p = new Properties();
        p.setProperty(VM_LOAD_PATH_KEY, VM_LOAD_PATH_VALUE);
        p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, StringPool.EMPTY);
        p.setProperty(Velocity.ENCODING_DEFAULT, UTF8);
        p.setProperty(Velocity.INPUT_ENCODING, UTF8);
        p.setProperty("file.resource.loader.unicode", StringPool.TRUE);
        this.velocityEngine = new VelocityEngine(p);
    }

    @Override
    protected void merge(String templateName, Map<String, Object> objectMap, File outputFile) throws Exception {
        String templateFilePath = templateFilePath(templateName);
        Template template = velocityEngine.getTemplate(templateFilePath, UTF8);
        try (FileOutputStream fos = new FileOutputStream(outputFile);
             OutputStreamWriter ow = new OutputStreamWriter(fos, UTF8);
             BufferedWriter writer = new BufferedWriter(ow)) {
            template.merge(new VelocityContext(objectMap), writer);
        }
        LOGGER.info("输出文件 [{}]，使用模板 [{}]", outputFile, templateFilePath);
        //LOGGER.debug("objectMap = {}", objectMap);
    }

    private String templateFilePath(String filePath) {
        final String dotVm = ".vm";
        return "/templates/" + (filePath.endsWith(dotVm) ? filePath : filePath + dotVm);
    }
}
